<

データをインターネットに送信する

ほとんどのアプリでは、インターネットへのデータの送信が必要です。 のhttpパッケージにもそれが含まれています。

このレシピでは次の手順を使用します。

  1. を追加します。httpパッケージ。
  2. を使用してサーバーにデータを送信します。httpパッケージ。
  3. 応答をカスタム Dart オブジェクトに変換します。
  4. 入手するtitleユーザー入力から。
  5. 応答を画面に表示します。

1.httpパッケージ

追加するには、httpパッケージを依存関係として、 走るflutter pub add:

$ flutter pub add http

インポートするhttpパッケージ。

import 'package:http/http.dart' as http;

Android向けに開発する場合は、 マニフェストタグ内に次の権限を追加します の中にAndroidManifest.xmlファイルは次の場所にありますandroid/app/src/main

<uses-permission android:name="android.permission.INTERNET"/>

2. サーバーへのデータ送信

このレシピでは、Albumアルバムタイトルを送信することで、JSONプレースホルダーを使用してhttp.post()方法。

輸入dart:convertにアクセスするためのjsonEncodeデータをエンコードするには:

import 'dart:convert';

使用http.post()エンコードされたデータを送信するメソッド:

Future<http.Response> createAlbum(String title) {
  return http.post(
    Uri.parse('https://jsonplaceholder.typicode.com/albums'),
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
    },
    body: jsonEncode(<String, String>{
      'title': title,
    }),
  );
}

http.post()メソッドはFutureが含まれているResponse

  • 854c9917-57d1-4ee1-8dfc-a​​3cc7093d5b6を操作するためのコア Dart クラスです。 非同期操作。 Future オブジェクトは可能性を表します 将来のある時点で使用可能になる値またはエラー。
  • http.Responseクラスには、成功したプログラムから受け取ったデータが含まれています httpコール。
  • createAlbum()メソッドは引数を取りますtitleサーバーに送信されて、Album

3. を変換します。http.Responseカスタム Dart オブジェクトへ

ネットワークリクエストを行うのは簡単ですが、 生のものを扱うFuture<http.Response>あまり便利ではありません。あなたの生活を楽にするために、 を変換しますhttp.ResponseDart オブジェクトに変換します。

アルバムクラスを作成する

まず、Albumを含むクラス ネットワークリクエストからのデータ。 これにはファクトリ コンストラクターが含まれています。 を作成しますAlbumJSONから。

JSON を手動で変換することは 1 つのオプションにすぎません。 詳細については、記事全文を参照してください。JSONとシリアル化

class Album {
  final int id;
  final String title;

  const Album({required this.id, required this.title});

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      id: json['id'],
      title: json['title'],
    );
  }
}

変換するhttp.ResponseAlbum

次の手順を使用して、createAlbum()を返す関数Future<Album>:

  1. レスポンスボディをJSONに変換するMapとともに79e74​​966-af44-4e2f-9fd2-d347c537fe8bパッケージ。
  2. サーバーがCREATEDステータス付きの応答 コード 201 を JSON に変換しますMapAlbumを使用してfromJson()ファクトリーメソッド。
  3. サーバーが応答を返さない場合は、CREATEDで応答します ステータス コード 201 の場合は、例外がスローされます。 (サーバー応答が「404 Not Found」の場合でも、 例外をスローします。戻らないでくださいnull。 調べるときに大事なこと のデータsnapshot、以下に示すように。)
Future<Album> createAlbum(String title) async {
  final response = await http.post(
    Uri.parse('https://jsonplaceholder.typicode.com/albums'),
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
    },
    body: jsonEncode(<String, String>{
      'title': title,
    }),
  );

  if (response.statusCode == 201) {
    // If the server did return a 201 CREATED response,
    // then parse the JSON.
    return Album.fromJson(jsonDecode(response.body));
  } else {
    // If the server did not return a 201 CREATED response,
    // then throw an exception.
    throw Exception('Failed to create album.');
  }
}

万歳!タイトルを送信する関数ができました。 アルバムを作成するためのサーバー。

4. ユーザー入力からタイトルを取得する

次に、TextFieldタイトルを入力し、 あるElevatedButtonデータをサーバーに送信します。 また、TextEditingControllerを読む ユーザーからの入力TextField

ときElevatedButtonが押されると、_futureAlbumによって返される値に設定されますcreateAlbum()方法。

Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    TextField(
      controller: _controller,
      decoration: const InputDecoration(hintText: 'Enter Title'),
    ),
    ElevatedButton(
      onPressed: () {
        setState(() {
          _futureAlbum = createAlbum(_controller.text);
        });
      },
      child: const Text('Create Data'),
    ),
  ],
)

を押すと、データの作成ボタンをクリックしてネットワークリクエストを行い、 データを送信しますTextFieldサーバーに としてPOSTリクエスト。 未来、_futureAlbum, 次のステップで使用されます。

5. 応答を画面に表示します

データを画面に表示するには、FutureBuilderウィジェット。 のFutureBuilderウィジェットには Flutter が付属しており、 非同期データ ソースの操作が簡単になります。 次の 2 つのパラメータを指定する必要があります。

  1. Future一緒に働きたいと思っています。この場合、 から戻ってきた未来createAlbum()関数。
  2. builderFlutterに何をレンダリングするかを指示する関数、 の状態に応じてFuture: 読み込み中、 成功かエラーか。

ご了承くださいsnapshot.hasDataのみを返しますtrueいつ スナップショットには null 以外のデータ値が含まれています。 このため、565ec50d-9c6a-4226-ベッド0-521a35d8d522関数は例外をスローする必要があります 「404 Not Found」サーバー応答の場合でも同様です。 もしもcreateAlbum()戻り値null、 それからCircularProgressIndicator無限に表示されます。

FutureBuilder<Album>(
  future: _futureAlbum,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return Text(snapshot.data!.title);
    } else if (snapshot.hasError) {
      return Text('${snapshot.error}');
    }

    return const CircularProgressIndicator();
  },
)

完全な例

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

Future<Album> createAlbum(String title) async {
  final response = await http.post(
    Uri.parse('https://jsonplaceholder.typicode.com/albums'),
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
    },
    body: jsonEncode(<String, String>{
      'title': title,
    }),
  );

  if (response.statusCode == 201) {
    // If the server did return a 201 CREATED response,
    // then parse the JSON.
    return Album.fromJson(jsonDecode(response.body));
  } else {
    // If the server did not return a 201 CREATED response,
    // then throw an exception.
    throw Exception('Failed to create album.');
  }
}

class Album {
  final int id;
  final String title;

  const Album({required this.id, required this.title});

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      id: json['id'],
      title: json['title'],
    );
  }
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  final TextEditingController _controller = TextEditingController();
  Future<Album>? _futureAlbum;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Create Data Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Create Data Example'),
        ),
        body: Container(
          alignment: Alignment.center,
          padding: const EdgeInsets.all(8),
          child: (_futureAlbum == null) ? buildColumn() : buildFutureBuilder(),
        ),
      ),
    );
  }

  Column buildColumn() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        TextField(
          controller: _controller,
          decoration: const InputDecoration(hintText: 'Enter Title'),
        ),
        ElevatedButton(
          onPressed: () {
            setState(() {
              _futureAlbum = createAlbum(_controller.text);
            });
          },
          child: const Text('Create Data'),
        ),
      ],
    );
  }

  FutureBuilder<Album> buildFutureBuilder() {
    return FutureBuilder<Album>(
      future: _futureAlbum,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Text(snapshot.data!.title);
        } else if (snapshot.hasError) {
          return Text('${snapshot.error}');
        }

        return const CircularProgressIndicator();
      },
    );
  }
}